package com.dd.cloud.user.service.phar.pharservice;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.dd.cloud.common.config.obs.PathProperties;
import com.dd.cloud.common.constants.PharConstants;
import com.dd.cloud.common.constants.PresConstants;
import com.dd.cloud.common.enums.ZkExceptionEnum;
import com.dd.cloud.common.exception.ZekeException;
import com.dd.cloud.common.interceptor.UserInterceptor;
import com.dd.cloud.common.utils.*;
import com.dd.cloud.common.vo.LoginInfo;
import com.dd.cloud.user.DTO.CallbackPresStatusReq;
import com.dd.cloud.user.DTO.CancelPresReq;
import com.dd.cloud.user.DTO.CommonParamReq;
import com.dd.cloud.user.DTO.dsl.*;
import com.dd.cloud.user.entity.doctor.PatientMedCard;
import com.dd.cloud.user.entity.order.OrderPay;
import com.dd.cloud.user.entity.phar.Pharmacy;
import com.dd.cloud.user.entity.phar.PharmacyDocking;
import com.dd.cloud.user.entity.pres.*;
import com.dd.cloud.user.enums.ExceptionEnum;
import com.dd.cloud.user.req.pres.PresCreateDslReq;
import com.dd.cloud.user.req.pres.PresCreateReq;
import com.dd.cloud.user.req.pres.PresPatientAddrReq;
import com.dd.cloud.user.service.doctor.IDoctorOrderIncomeDetailService;
import com.dd.cloud.user.service.log.ILogErrorService;
import com.dd.cloud.user.service.order.IOrderPayService;
import com.dd.cloud.user.service.phar.IPharmacyDockingService;
import com.dd.cloud.user.service.phar.IPharmacyService;
import com.dd.cloud.user.service.pres.*;
import com.dd.cloud.user.service.sms.ISmsService;
import com.dd.cloud.user.vo.DslExpressRes;
import com.dd.cloud.user.vo.DslResponseVo;
import com.dd.cloud.user.vo.ExpressRes;
import com.dd.cloud.user.vo.PharResponseVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 * @Description: // 大参林药房操作，
 * @ClassName: HjtPharService
 * @Author: czg
 * @Date: 2022/11/25 17:20
 * @Version: 1.0
 */
@Slf4j
@Service
public class DslPharService extends PharAbstractService {
    @Autowired
    private IPresDslDetailService presDslDetailService;
    @Autowired
    private IPresDslPharRoamService presDslPharRoamService;
    @Autowired
    private IOrderPayService orderPayService;
    @Autowired
    private ILogErrorService logErrorService;
    @Autowired
    private IPresPrescriptionService presPrescriptionService;
    @Autowired
    private IPharmacyService pharmacyService;
    @Autowired
    private IPresPretrialDrugsService presPretrialDrugsService;
    @Autowired
    private IPharmacyDockingService pharmacyDockingService;
    @Autowired
    private PathProperties pathProperties;
    @Autowired
    private IPresHandleRecordService presHandleRecordService;
    @Autowired
    private IDoctorOrderIncomeDetailService doctorOrderIncomeDetailService;
    @Autowired
    private ISmsService smsService;

    /**
     * 添加药房的处方详情
     *
     * @param req
     * @param medCard
     */
    @Override
    public void addPresDetail(PresCreateReq req, PatientMedCard medCard) {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo().get();
        PresCreateDslReq dslReq = (PresCreateDslReq) req;
        PresDslDetail detail = new PresDslDetail();
        BeanUtils.copyProperties(dslReq, detail);
        BeanUtils.copyProperties(medCard, detail);
        detail.setIsSendHos(1);
        detail.setPatientName(medCard.getName());
        detail.setRecipelInstru(dslReq.getDisease());
        detail.setIsHos(0);
        detail.setPatientId(medCard.getMedId());
        detail.setIsPregnant(medCard.getPregnant() == 1 ? 0 : 1);
        detail.setSex("男".equals(medCard.getSex()) ? 0 : 1);
        Integer age = CalendarUtil.getAge(medCard.getBirthDate());
        detail.setAge(age == null ? null : String.valueOf(age));
        detail.setDoctor(loginInfo.getName());
        detail.setPatientTel(medCard.getMobileNumber());
        detail.setPerPackNum(req.getDoseNum());
        detail.setPerPackDose(req.getDrugDose());
        detail.setCreateDate(LocalDateTime.now());
        boolean i = presDslDetailService.saveOrUpdate(detail);
        if (!i) {
            throw new ZekeException(ExceptionEnum.PRES_CREATE_ERROR, "处方信息保存失败");
        }
    }

    /**
     * @param pay: 支付回调调用, 订单参数
     * @return void
     * @author czg
     * @description 发送处方到大参林药房, 参考接口文档<<智慧药房医院接口文档HTTP协议>>
     * @date 2022/11/28 14:19
     */
    @Override
    public boolean sendPresToPhar(OrderPay pay) {
        log.info("发送处方到大参林药房");
        boolean succ = false;
        if (StringUtils.isBlank(pay.getServerNo())) {
            //没有处方编码 数据异常, 退款
            orderPayService.refund(pay.getOrderNo(), 0);
            logErrorService.presBackLog("没有处方编码-数据异常, 退款", "处方发送到大参林药房异常", "tencode=" + pay.getServerNo());
            return succ;
        }
        PresPrescription presPrescription = presPrescriptionService.getById(pay.getServerNo());
        if (presPrescription == null) {
            //处方为空, 数据异常, 退款
//            orderPayService.refund(pay.getOrderNo(), 0);
            presPrescription.setStatus(PresConstants.PresStatus.SENDPHARMERROR);
            presPrescriptionService.updateById(presPrescription);
            logErrorService.presBackLog("处方为空-数据异常", "处方发送到大参林药房异常", "tencode=" + pay.getServerNo());
            return succ;
        }
        if (presPrescription.getStatus() == PresConstants.PresStatus.SENDPHARM) {
            //处方已发送到药房, 此为重复回调
            log.info("处方已发送到药房, 此为重复回调");
            return succ;
        }
        PresDslDetail dslDetail = presDslDetailService.getById(pay.getServerNo());
        if (dslDetail == null) {
//            orderPayService.refund(pay.getOrderNo(), 0);
            presPrescription.setStatus(PresConstants.PresStatus.SENDPHARMERROR);
            presPrescriptionService.updateById(presPrescription);
            logErrorService.presBackLog("获取发送给药房的详细数据失败", "处方发送到大参林药房异常", "tencode=" + pay.getServerNo());
            return succ;
        }
        Pharmacy pharmacy = pharmacyService.getById(presPrescription.getPharmId());
        if (pharmacy == null) {
            //药房为空, 数据异常 ,退款
//            orderPayService.refund(pay.getOrderNo(), 0);
            presPrescription.setStatus(PresConstants.PresStatus.SENDPHARMERROR);
            presPrescriptionService.updateById(presPrescription);
            logErrorService.presBackLog("药房为空-数据异常, 退款", "处方发送到大参林药房异常", "tencode=" + pay.getServerNo());
            return succ;
        }
        QueryWrapper<PharmacyDocking> qd = new QueryWrapper<>();
        qd.lambda().eq(PharmacyDocking::getPharId, pharmacy.getId()).eq(PharmacyDocking::getStatus, PharConstants.DockingStatus.NOMER);
        PharmacyDocking pharmacyDocking = pharmacyDockingService.getOne(qd);
        if (pharmacyDocking == null) {
            //药房为空, 数据异常 ,退款
//            orderPayService.refund(pay.getOrderNo(), 0);
            presPrescription.setStatus(PresConstants.PresStatus.SENDPHARMERROR);
            presPrescriptionService.updateById(presPrescription);
            logErrorService.presBackLog("药房对接信息为空-数据异常", "处方发送到大参林药房异常", "pharId=" + pharmacy.getId());
            return succ;
        }
        SendPresHeadDTO head = new SendPresHeadDTO();
        SendPresBodyDTO body = new SendPresBodyDTO();
        SendPresPersionDTO presPersionDTO = new SendPresPersionDTO();
        SendPresPersionDTO.PresPersionListDTO persion = presPersionDTO.new PresPersionListDTO();
        QueryWrapper<PresPretrialDrugs> qw = new QueryWrapper<>();
        qw.lambda().eq(PresPretrialDrugs::getTencode, presPrescription.getTencode()).eq(PresPretrialDrugs::getStatus, PresConstants.PresDrugsStatus.NOMER);
        List<PresPretrialDrugs> drugsList = presPretrialDrugsService.list(qw);
        if (drugsList == null || drugsList.isEmpty()) {
            //没有处方药品, 数据异常, 退款
//            orderPayService.refund(pay.getOrderNo(), 0);
            presPrescription.setStatus(PresConstants.PresStatus.SENDPHARMERROR);
            presPrescriptionService.updateById(presPrescription);
            logErrorService.presBackLog("没有处方药品-数据异常", "处方发送到大参林药房异常", "tencode=" + pay.getServerNo());
            return succ;
        }
        /**
         * 药品详情
         */
        List<SendPresDrugDTO.PresDrugDTO> list = new LinkedList<SendPresDrugDTO.PresDrugDTO>();
        SendPresDrugDTO presDrugDTO = new SendPresDrugDTO();
        for (PresPretrialDrugs drugs : drugsList) {
            SendPresDrugDTO.PresDrugDTO drugDTO = presDrugDTO.new PresDrugDTO();
            BeanUtils.copyProperties(drugs, drugDTO);
            drugDTO.setHosMedName(drugs.getHerbName());
            drugDTO.setHosMedCode(drugs.getDrugnum());
            drugDTO.setHosMedDose(drugs.getDrugallnum());
            drugDTO.setHosMedNorms(drugs.getSpecification());
            drugDTO.setHosMedType(0);
            drugDTO.setHosMedUnit(drugs.getUnit());
            drugDTO.setHosMedUnitPrice(BigDecimalUtils.divide(BigDecimal.valueOf(drugs.getRetailprice()), BigDecimal.valueOf(100), 4).doubleValue());
            drugDTO.setSpecialDecoctingMethod(drugs.getDrugdescription());
            list.add(drugDTO);
        }
        presDrugDTO.setMedDetail(list);
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime time = LocalDateTime.now();
        BeanUtils.copyProperties(dslDetail, body);
        BeanUtils.copyProperties(dslDetail, persion);
        persion.setAmount(presPrescription.getAllDose());
        persion.setHosRecipelNo(presPrescription.getTencode());
        persion.setIsHos(0);
        String signUrl;
        if (!StringUtils.isBlank(presPrescription.getConfirmSign())) {
            signUrl = pathProperties.getImageServer() + presPrescription.getConfirmSign();
            persion.setDoubleSignatureImage(ImageUtils.imageUrlToBase64(signUrl));
            persion.setDoubleSignatureImageName(FilenameUtils.getName(signUrl));
        }
        persion.setRecipelDetail(presDrugDTO);
        List<SendPresPersionDTO.PresPersionListDTO> persionList = new ArrayList();
        persionList.add(persion);
        presPersionDTO.setRecipel(persionList);
        body.setPayStatus(1);
        body.setChargingTime(df.format(time));
        body.setIsSendHos(1);
        body.setCheckCallbackUrl(pharmacyDocking.getPresCallbackUrl() + CodecUtils.md5Hex(pay.getServerNo(), "status"));
        body.setExpressUrlCallback(pharmacyDocking.getExpressUrl() + CodecUtils.md5Hex(pay.getServerNo(), "express"));
        body.setRecipelList(presPersionDTO);
        //转json字符串 参数要求下划线, 所以驼峰需要转下划线
        String bodyJson = JsonUtils.objectToStrStrategy(body);
        /**
         * body字符串base64加密
         */
        log.info("body参数:{}", bodyJson);
        String bodyBase64 = null;
        try {
            bodyBase64 = Base64.encodeBase64String(bodyJson.getBytes(StandardCharsets.UTF_8));
        } catch (Exception e) {
            e.printStackTrace();
        }
        head.setHos_id(pharmacyDocking.getMchId());
        head.setCharset("utf8");
        head.setTimestamp(df.format(time));
        head.setFormat("JSON");
        head.setRequest_body(bodyBase64);
        //token 规则bodybase64加密后+时间字符串+秘钥 整体md5加密
        String tokenStr = head.getRequest_body() + head.getTimestamp() + pharmacyDocking.getEncryptyKey();
        head.setToken(Md5Utils.hash(tokenStr));
        log.info("发送参数:{}", head);
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        params.add(new BasicNameValuePair("hos_id", pharmacyDocking.getMchId()));
        params.add(new BasicNameValuePair("token", Md5Utils.hash(tokenStr)));
        params.add(new BasicNameValuePair("format", "JSON"));
        params.add(new BasicNameValuePair("charset", "utf-8"));
        params.add(new BasicNameValuePair("request_body", bodyBase64));
        params.add(new BasicNameValuePair("timestamp", df.format(time)));
        //发送处方到药房
        String result;
        try {
            //发送处方到大参林药房
            log.info("发送url:{}", pharmacyDocking.getServicesUrl());
            result = HttpRequestUtils.post(pharmacyDocking.getServicesUrl(), params, "application/x-www-form-urlencoded", "utf-8");
            System.out.println("大参林药房返回:{}," + result);
        } catch (Exception e) {
            e.printStackTrace();
//            orderPayService.refund(pay.getOrderNo(), 0);
            presPrescription.setStatus(PresConstants.PresStatus.SENDPHARMERROR);
            presPrescriptionService.updateById(presPrescription);
            logErrorService.presBackLog("发送处方失败-数据异常", "处方发送到大参林药房异常", "tencode=" + pay.getServerNo());
            return succ;
        }
        DataResDTO resDTO;
        try {
            resDTO = JsonUtils.parse(result, DataResDTO.class);
        } catch (Exception e) {
//            orderPayService.refund(pay.getOrderNo(), 0);
            presPrescription.setStatus(PresConstants.PresStatus.SENDPHARMERROR);
            presPrescriptionService.updateById(presPrescription);
            logErrorService.presBackLog("药房返回数据json解析失败", "处方发送到大参林药房异常", "res=" + result);
            return succ;
        }
        if (!"200".equals(resDTO.getCode())) {
            //接口返回异常 退款
//            orderPayService.refund(pay.getOrderNo(), 0);
            presPrescription.setStatus(PresConstants.PresStatus.SENDPHARMERROR);
            presPrescriptionService.updateById(presPrescription);
            logErrorService.presBackLog("药房返回状态码异常", "处方发送到大参林药房异常", "msg=" + resDTO.getMsg());
            return succ;
        }
        presPrescription.setStatus(PresConstants.PresStatus.SENDPHARM);
        presPrescription.setUpdateDate(LocalDateTime.now());
        boolean flag = presPrescriptionService.updateById(presPrescription);
        if (!flag) {
            presPrescription.setStatus(PresConstants.PresStatus.SENDPHARMERROR);
            presPrescriptionService.updateById(presPrescription);
            logErrorService.presBackLog("发送处方到药房成功, 处方更新失败", "处方发送到大参林药房异常", "jsonBody=" + presPrescription);
            return succ;
        }
        dslDetail.setOrderNO(resDTO.getData().getOrder_no());
        presDslDetailService.updateById(dslDetail);
        succ = true;
        return succ;
    }

    /**
     * @param req:
     * @return void
     * @author czg
     * @description 取消处方
     * @date 2022/12/2 9:45
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelPres(CancelPresReq req) {
        PresPrescription presPrescription = presPrescriptionService.getById(req.getTencode());
        if (presPrescription == null) {
            throw new ZekeException(ZkExceptionEnum.CANCEL_PRES_ERROR, "查询处方失败");
        }
        Pharmacy pharmacy = pharmacyService.getById(presPrescription.getPharmId());
        if (pharmacy == null) {
            throw new ZekeException(ZkExceptionEnum.CANCEL_PRES_ERROR, "查询药房失败");
        }
        QueryWrapper<PharmacyDocking> qd = new QueryWrapper<>();
        qd.lambda().eq(PharmacyDocking::getPharId, pharmacy.getId()).eq(PharmacyDocking::getStatus, PharConstants.DockingStatus.NOMER);
        PharmacyDocking pharmacyDocking = pharmacyDockingService.getOne(qd);
        if (pharmacyDocking == null) {
            throw new ZekeException(ZkExceptionEnum.CANCEL_PRES_ERROR, "查询药房信息失败");
        }
        CancelPresDTO cancelPresDTO = new CancelPresDTO();
        cancelPresDTO.setHosRecipelNo(req.getTencode());
        cancelPresDTO.setCanceller(req.getCancelMsg());
        cancelPresDTO.setCancelReason(req.getOperName());
        //转json字符串 参数要求下划线, 所以驼峰需要转下划线
        String bodyJson = JsonUtils.objectToStrStrategy(cancelPresDTO);
        String bodyBase64 = null;
        try {
            bodyBase64 = Base64.encodeBase64String(bodyJson.getBytes(StandardCharsets.UTF_8));
        } catch (Exception e) {
            e.printStackTrace();
            throw new ZekeException(ZkExceptionEnum.CANCEL_PRES_ERROR, "参数转base64失败");
        }
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime time = LocalDateTime.now();
        //token 规则bodybase64加密后+时间字符串+秘钥 整体md5加密
        String tokenStr = bodyBase64 + df.format(time) + pharmacyDocking.getEncryptyKey();
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        params.add(new BasicNameValuePair("hos_id", pharmacyDocking.getMchId()));
        params.add(new BasicNameValuePair("token", Md5Utils.hash(tokenStr)));
        params.add(new BasicNameValuePair("format", "JSON"));
        params.add(new BasicNameValuePair("charset", "utf-8"));
        params.add(new BasicNameValuePair("request_body", bodyBase64));
        params.add(new BasicNameValuePair("timestamp", df.format(time)));
        //发送处方到药房
        String result;
        try {
            //发送处方到大参林药房
            log.info("发送url:{}", pharmacyDocking.getCancelUrl());
            result = HttpRequestUtils.post(pharmacyDocking.getCancelUrl(), params, "application/x-www-form-urlencoded", "utf-8");
            System.out.println("大参林药房返回:{}," + result);
        } catch (Exception e) {
            e.printStackTrace();
            throw new ZekeException(ZkExceptionEnum.CANCEL_PRES_ERROR, "调用药房取消处方接口异常");
        }
        DataResDTO resDTO;
        try {
            resDTO = JsonUtils.parse(result, DataResDTO.class);
        } catch (Exception e) {
            e.printStackTrace();
            throw new ZekeException(ZkExceptionEnum.CANCEL_PRES_ERROR, "药房接口解析失败,请联系管理员");
        }
        if (!"200".equals(resDTO.getCode())) {
            throw new ZekeException(ZkExceptionEnum.CANCEL_PRES_ERROR, resDTO.getMsg());
        }
        presPrescription.setStatus(PresConstants.PresStatus.CANCEL);
        boolean flag = presPrescriptionService.updateById(presPrescription);
        if (!flag) {
            logErrorService.presBackLog("取消处方大参林返回成功,数据修改失败", "取消处方", "tencode=" + presPrescription.getTencode());
            throw new ZekeException(ZkExceptionEnum.CANCEL_PRES_ERROR, "数据修改失败,请联系管理员");
        }
    }

    /**
     * @param req:
     * @return PharResponseVo
     * @author czg
     * @description 大参林处方状态回传
     * @date 2022/12/5 15:38
     */
    @Override
    public PharResponseVo presCallback(CallbackPresStatusReq req) {
        log.info("大参林药房回调");
        DslStatusReportReq dslReq = (DslStatusReportReq) req.toStatusPojo();
        QueryWrapper<PresDslDetail> qw = new QueryWrapper<>();
        qw.lambda().eq(PresDslDetail::getOrderNO, dslReq.getOrderNo());
        PresDslDetail dslDetail = presDslDetailService.getOne(qw);
        if (dslDetail == null) {
            logErrorService.presBackLog("处方订单号不存在", "大参林回调处方状态异常", "orderNo=" + dslReq.getOrderNo());
            throw new ZekeException(ZkExceptionEnum.PARAMETER_ERROR, "处方订单号不存在");
        }
        PresPrescription presPrescription = presPrescriptionService.getById(dslDetail.getTencode());
        if (presPrescription == null) {
            logErrorService.presBackLog("处方编号号不存在", "大参林回调处方状态异常", "tencode=" + dslDetail.getTencode());
            throw new ZekeException(ZkExceptionEnum.PARAMETER_ERROR, "处方编号号不存在");
        }
        DslResponseVo responseVo = new DslResponseVo();
        if (!dslReq.getParam().equals(CodecUtils.md5Hex(presPrescription.getTencode(), "status"))) {
            logErrorService.presBackLog("大参林状态回调自定义参数错误", "大参林状态回调自定义参数被篡改", "tencode=" + presPrescription.getTencode());
            responseVo.setCode("1004");
            responseVo.setMsg("自定义参数被篡改");
            return responseVo;
        }
        int status;
        switch (dslReq.getStatus()) {
            case PresConstants.DslPresStatus.AUDITSUC:
                status = PresConstants.PresStatus.AUDIT;
                break;
            case PresConstants.DslPresStatus.ADJUSTNO:
                status = PresConstants.PresStatus.AUDITNO;
                break;
            default:
                responseVo.setCode("1004");
                responseVo.setMsg("参数数据有误");
                return responseVo;
        }
        if (presPrescription.getStatus().equals(status)) {
            //重复请求
            responseVo.setCode("200");
            responseVo.setMsg("SUCCESS");
            return responseVo;
        }
        presPrescription.setStatus(status);
        presPrescription.setUpdateDate(LocalDateTime.now());
        boolean flag = presPrescriptionService.updateById(presPrescription);
        if (!flag) {
            logErrorService.presBackLog("修改处方信息失败", "大参林回调处方信息异常", "tencode=" + dslDetail.getTencode());
        }
        QueryWrapper<PresDslPharRoam> qr = new QueryWrapper<>();
        qr.lambda().eq(PresDslPharRoam::getTencode, presPrescription.getTencode()).last("limit 1");
        PresDslPharRoam roam = presDslPharRoamService.getOne(qr);
        if (roam != null) {
            logErrorService.presBackLog("处方流转信息已存在", "大参林回调处方信息异常", "tencode=" + dslDetail.getTencode());
            responseVo.setCode("200");
            responseVo.setMsg("SUCCESS");
            return responseVo;
        }
        roam = new PresDslPharRoam();
        BeanUtils.copyProperties(dslReq, roam);
        roam.setTencode(presPrescription.getTencode());
        roam.setCreateDate(LocalDateTime.now());
        flag = presDslPharRoamService.save(roam);
        if (!flag) {
            logErrorService.presBackLog("保存处方流转信息失败", "大参林回调处方信息异常", "tencode=" + dslDetail.getTencode());
        }
        try {
            PresHandleRecord handleRecord = new PresHandleRecord();
            handleRecord.setTencode(presPrescription.getTencode());
            handleRecord.setCreateId(0);
            handleRecord.setCreateType(0);
            handleRecord.setCreateDate(LocalDateTime.now());
            handleRecord.setStatus(status);
            handleRecord.setRejectReason(dslReq.getDescribe());
            presHandleRecordService.save(handleRecord);
        } catch (Exception e) {
            e.printStackTrace();
        }
        responseVo.setCode("200");
        responseVo.setMsg("SUCCESS");
        return responseVo;
    }

    /**
     * @param req:
     * @return void
     * @author czg
     * @description 物流信息回调
     * @date 2022/12/6 10:24
     */
    @Override
    public PharResponseVo expressCallback(CommonParamReq req) {
        log.info("大参林物流回调");
        DslExpressReportReq dslReq = (DslExpressReportReq) req.toExpressPojo();
        QueryWrapper<PresDslDetail> qw = new QueryWrapper<>();
        qw.lambda().eq(PresDslDetail::getOrderNO, dslReq.getOrderNo());
        PresDslDetail dslDetail = presDslDetailService.getOne(qw);
        if (dslDetail == null) {
            logErrorService.presBackLog("处方订单号不存在", "大参林回调处方状态异常", "orderNo=" + dslReq.getOrderNo());
            throw new ZekeException(ZkExceptionEnum.PARAMETER_ERROR, "处方订单号不存在");
        }
        PresPrescription presPrescription = presPrescriptionService.getById(dslDetail.getTencode());
        if (presPrescription == null) {
            logErrorService.presBackLog("处方编号号不存在", "大参林回调处方状态异常", "tencode=" + dslDetail.getTencode());
            throw new ZekeException(ZkExceptionEnum.PARAMETER_ERROR, "处方编号号不存在");
        }
        DslResponseVo responseVo = new DslResponseVo();
        if (!dslReq.getParam().equals(CodecUtils.md5Hex(presPrescription.getTencode(), "express"))) {
            logErrorService.presBackLog("大参林物流回调自定义参数错误", "大参林物流回调自定义参数被篡改", "tencode=" + presPrescription.getTencode());
            responseVo.setCode("1004");
            responseVo.setMsg("自定义参数被篡改");
            return responseVo;
        }
        int status;
        switch (dslReq.getType()) {
            case PresConstants.DslPresType.OUTBOUND:
                status = PresConstants.PresStatus.DELIVERY;
                presPrescription.setExpressno(dslReq.getThirdExpressWaybillNo());
                presPrescription.setExpresscompany(dslReq.getLogisCompanyName());
                smsService.sendDeliveryPres(presPrescription.getTencode(), presPrescription.getDoctorId(), presPrescription.getName(), dslReq.getThirdExpressWaybillNo(), dslReq.getLogisCompanyName());
                break;
            case PresConstants.DslPresType.SIGNIN:
                status = PresConstants.PresStatus.SUC;
                doctorOrderIncomeDetailService.doctorOrderIncomeEntrySuc(presPrescription.getTencode(), presPrescription.getDoctorId());
                break;
            default:
                responseVo.setCode("1004");
                responseVo.setMsg("参数数据有误");
                return responseVo;
        }
        if (presPrescription.getStatus().equals(status)) {
            //重复请求
            responseVo.setCode("200");
            responseVo.setMsg("SUCCESS");
            return responseVo;
        }
        presPrescription.setStatus(status);
        presPrescription.setUpdateDate(LocalDateTime.now());
        boolean flag = presPrescriptionService.updateById(presPrescription);
        if (!flag) {
            logErrorService.presBackLog("修改处方信息失败", "大参林回调处方信息异常", "tencode=" + dslDetail.getTencode());
        }
        QueryWrapper<PresDslPharRoam> qr = new QueryWrapper<>();
        qr.lambda().eq(PresDslPharRoam::getTencode, presPrescription.getTencode()).last("limit 1");
        PresDslPharRoam roam = presDslPharRoamService.getOne(qr);
        if (roam != null) {
            BeanUtils.copyProperties(dslReq, roam);
            if (dslReq.getType() == PresConstants.DslPresType.OUTBOUND) {
                roam.setOutboundDate(LocalDateTime.now());
            }
            flag = presDslPharRoamService.updateById(roam);
            if (!flag) {
                logErrorService.presBackLog("修改处方流转信息失败", "大参林回调处方信息异常", "tencode=" + dslDetail.getTencode());
            }
        } else {
            roam = new PresDslPharRoam();
            BeanUtils.copyProperties(dslReq, roam);
            roam.setCreateDate(LocalDateTime.now());
            flag = presDslPharRoamService.save(roam);
            if (!flag) {
                logErrorService.presBackLog("保存处方流转信息失败", "大参林回调处方信息异常", "tencode=" + dslDetail.getTencode());
            }
        }
        responseVo.setCode("200");
        responseVo.setMsg("SUCCESS");
        return responseVo;
    }

    /**
     * 修改收货人信息
     *
     * @param req
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePresPatientAddrInfo(PresPatientAddrReq req) {
        UpdateWrapper<PresDslDetail> uw = new UpdateWrapper<>();
        uw.lambda().eq(PresDslDetail::getTencode, req.getTencode());
        uw.lambda().set(PresDslDetail::getConsigneeName, req.getReceiver());
        uw.lambda().set(PresDslDetail::getConsigneePhone, req.getMobileNumber());
        uw.lambda().set(PresDslDetail::getConsigneeProvince, req.getProvince());
        uw.lambda().set(PresDslDetail::getConsigneeCity, req.getCity());
        uw.lambda().set(PresDslDetail::getConsigneeRegion, req.getDistrict());
        uw.lambda().set(PresDslDetail::getConsigneeDetailAddress, req.getAddr());
        boolean flag = presDslDetailService.update(uw);
        if (!flag) {
            throw new ZekeException(400, "修改处方收货人信息失败");
        }
    }

    @Override
    public List<ExpressRes> queryLogisticsInfo(String tencode) {
        QueryWrapper<PresDslDetail> qw = new QueryWrapper<>();
        qw.lambda().eq(PresDslDetail::getTencode, tencode);
        qw.lambda().select(PresDslDetail::getOrderNO);
        PresDslDetail dsl = presDslDetailService.getOne(qw);
        if (dsl == null) {
            throw new ZekeException(400, "未查到处方信息");
        }
        List<ExpressRes> resList = new ArrayList<>();
        try {
            String result = HttpRequestUtils.get(DslExpressRes.API + dsl.getOrderNO());
            DslExpressRes dslLogisticsRes = JSON.parseObject(result, DslExpressRes.class);
            int type = 1;
            for (DslExpressRes.Data t : dslLogisticsRes.getData()) {
                ExpressRes res = new ExpressRes(t);
                if (res.getExpressTrackDetail().contains("已出库")) {
                    type = 2;
                }
                if (res.getExpressTrackDetail().contains("已收取快件")) {
                    type = 3;
                }
                if (res.getExpressTrackDetail().contains("准备发往")) {
                    type = 4;
                }
                if (res.getExpressTrackDetail().contains("电话")) {
                    type = 5;
                }
                if (res.getExpressTrackDetail().contains("已签收")) {
                    type = 6;
                }
                res.setTencode(tencode);
                res.setType(type);
                resList.add(res);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return resList;
    }
}
